package com.aplink.generic.util;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;

import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Environment;

import com.aplink.generic.GenericApplication;
import com.aplink.generic.network.GenericFile;

public class BitmapUtis {
	private static BitmapUtis sInstance = null;

	public static BitmapUtis getInstance() {
		if (BitmapUtis.sInstance == null) {
			BitmapUtis.sInstance = new BitmapUtis();
		}
		return BitmapUtis.sInstance;
	}

	private BitmapUtis() {
	}

	private int calculateInSampleSize(final BitmapFactory.Options options,
	        final int reqWidth, final int reqHeight) {
		final int height = options.outHeight;
		final int width = options.outWidth;
		int inSampleSize = 1;

		if ((height > reqHeight) || (width > reqWidth)) {

			final int halfHeight = height / 2;
			final int halfWidth = width / 2;

			while (((halfHeight / inSampleSize) > reqHeight)
			        && ((halfWidth / inSampleSize) > reqWidth)) {
				inSampleSize *= 2;
			}

			long totalPixels = (width * height) / inSampleSize;

			final long totalReqPixelsCap = reqWidth * reqHeight * 2;

			while (totalPixels > totalReqPixelsCap) {
				inSampleSize *= 2;
				totalPixels /= 2;
			}
		}
		return inSampleSize;
	}

	public GenericFile createTempFile(final String filename) {
		GenericFile genericFile = new GenericFile();
		String path = null;
		Boolean isSDPresent = Environment.getExternalStorageState().equals(
		        android.os.Environment.MEDIA_MOUNTED);
		if (isSDPresent) {
			path = Environment.getExternalStorageDirectory().toString();
		} else {

		}
		final String applicationName = GenericApplication.getInstance()
		        .getApplicationName();
		File file = new File(path + "/" + applicationName);
		if (!file.exists()) {
			file.mkdir();
		}

		try {
			file = File.createTempFile(filename, ".jpg", new File(path + "/"
			        + applicationName));

			LogUtil.info("saved: " + "file://" + file.toString(), "saved file",
			        getClass());
			genericFile.setLocalPath(file.toString());
			genericFile.setExtension(".jpg");
			genericFile.setName(filename);
			return genericFile;
		} catch (final Exception e) {
			LogUtil.error(e.getMessage(), "save file:" + file.toString(),
			        getClass());
		}
		return null;
	}

	public Bitmap decodeSampledBitmapFromFile(final String filename,
	        final int reqWidth, final int reqHeight) {
		final BitmapFactory.Options options = new BitmapFactory.Options();
		options.inJustDecodeBounds = true;
		BitmapFactory.decodeFile(filename, options);
		getDefaultOptions().inSampleSize = calculateInSampleSize(options,
		        reqWidth, reqHeight);
		return BitmapFactory.decodeFile(filename, getDefaultOptions());
	}

	public Bitmap decodeSampledBitmapFromResource(final Resources res,
	        final int resId, final int reqWidth, final int reqHeight) {
		final BitmapFactory.Options options = new BitmapFactory.Options();
		options.inJustDecodeBounds = true;
		BitmapFactory.decodeResource(res, resId, options);
		getDefaultOptions().inSampleSize = calculateInSampleSize(options,
		        reqWidth, reqHeight);
		return BitmapFactory.decodeResource(res, resId, getDefaultOptions());
	}

	public Bitmap decodeThumbnailBitmapFromFile(final String filename) {
		return decodeSampledBitmapFromFile(filename, 320, 240);
	}

	public Bitmap decodeThumbnailBitmapFromResource(final Resources res,
	        final int resId) {
		return decodeSampledBitmapFromResource(res, resId, 320, 240);
	}

	public GenericFile download(final String physicalPath) {
		final GenericFile genericFile = new GenericFile();
		try {
			final String extStorageDirectory = Environment
			        .getExternalStorageDirectory().toString();
			final String applicationName = GenericApplication.getInstance()
			        .getApplicationName();
			final File file = new File(extStorageDirectory + "/"
			        + applicationName);
			if (!file.exists()) {
				file.mkdir();
			}
			final URL url = new URL(physicalPath);
			String fileName = null;
			String fileExtension = null;
			final URLConnection connection = url.openConnection();
			final String disposition = connection
			        .getHeaderField("Content-Disposition");

			if (disposition != null) {
				final int index = disposition.indexOf("filename=");
				if (index > 0) {
					fileName = disposition.substring(index + 10,
					        disposition.length() - 1);
				}
			} else {
				fileName = physicalPath.substring(
				        physicalPath.lastIndexOf("/") + 1,
				        physicalPath.length());
			}
			final int index = fileName.lastIndexOf(".");
			fileExtension = fileName.substring(index, fileName.length());
			final InputStream input = connection.getInputStream();
			final File storagePath = new File(extStorageDirectory + "/"
			        + applicationName, fileName);

			genericFile.setLocalPath(storagePath.toString());
			genericFile.setName(fileName);
			genericFile.setPhysicalPath(physicalPath);
			genericFile.setExtension(fileExtension);

			if (storagePath.exists()) {
				LogUtil.info("Exists: " + "file://" + storagePath.toString(),
				        "Download file:" + physicalPath, getClass());
				return genericFile;
			}
			final OutputStream output = new FileOutputStream(storagePath);
			try {
				final byte[] buffer = new byte[1024];
				int bytesRead = 0;
				while ((bytesRead = input.read(buffer, 0, buffer.length)) >= 0) {
					output.write(buffer, 0, bytesRead);
				}
				LogUtil.info(
				        "downloaded: " + "file://" + storagePath.toString(),
				        "Download file:" + physicalPath, getClass());
				return genericFile;
			} finally {
				output.close();
			}
		} catch (final IOException e) {
			LogUtil.error(e.getMessage(), "Download file:" + physicalPath,
			        getClass());
		}
		return null;
	}

	private BitmapFactory.Options getDefaultOptions() {
		final BitmapFactory.Options options = new BitmapFactory.Options();
		options.inScaled = false;
		options.inPreferredConfig = Bitmap.Config.ARGB_8888;
		options.inDither = false;
		options.inJustDecodeBounds = false;
		options.inPurgeable = true;
		options.inInputShareable = true;
		options.inTempStorage = new byte[16 * 1024];
		return options;
	}

	public GenericFile savebitmap(final Bitmap bitmap) {
		final String filename = null;
		return this.savebitmap(filename, bitmap);
	}

	public GenericFile savebitmap(final String filename, final Bitmap bitmap) {
		final GenericFile genericFile = new GenericFile();
		final String extStorageDirectory = Environment
		        .getExternalStorageDirectory().toString();
		final String applicationName = GenericApplication.getInstance()
		        .getApplicationName();
		OutputStream outStream = null;
		File file = new File(extStorageDirectory + "/" + applicationName);
		if (!file.exists()) {
			file.mkdir();
		}
		file = new File(extStorageDirectory + "/" + applicationName, filename
		        + ".jpg");
		try {
			outStream = new FileOutputStream(file);
			bitmap.compress(Bitmap.CompressFormat.JPEG, 70, outStream);
			outStream.flush();
			outStream.close();
			LogUtil.info("saved: " + "file://" + file.toString(), "saved file",
			        getClass());
			genericFile.setLocalPath(file.toString());
			genericFile.setExtension(".jpg");
			genericFile.setName(filename);
			return genericFile;
		} catch (final Exception e) {
			LogUtil.error(e.getMessage(), "save file:" + file.toString(),
			        getClass());
		}
		return null;
	}
}
